package com.lsa.skienna.challenge.chap4.the110401_VitosFamily;

import java.io.File;
import java.io.FileInputStream;

import com.lsa.helpers.Utils;
import com.lsa.skienna.challenge.chap4.the110401_VitosFamily.Main.Task;
import com.lsa.skienna.challenge.chap4.the110401_VitosFamily.Main.TaskReader;

import junit.framework.TestCase;

public class Test_VitosFamily extends TestCase {
	public void test1() throws Exception {
		File inpFile = new File("data/pc4/110401_VitosFamily/110401.inp");
		
		TaskReader taskReader = new TaskReader(new FileInputStream(inpFile));
		Task task;
		
		int[] optimals = {2,4};
		int j = -1;
		
		while( (task = taskReader.nextTask()) != null) {
			if (++j == optimals.length) {
				assertTrue("Not all task was processed!", false);
			}
			int optimal = Main.optimalLocationSumOfDistances(task);
			assertTrue(optimal == optimals[j]);
		}
	}
	
	public void testOnRandomTasks() throws Exception {
//		int[] duplCount = {1,10,50,99, 100};
		int[] duplCount = {98};
		int relNumber = 100;
		int addrLower = 1;
		int addrUpper = 100;
		for (int i : duplCount) {
			testOnRandomTask(relNumber, addrLower, addrUpper,  i);
		}
		
		testOnRandomTask(199, 1, 100, 0);
		testOnRandomTask(500, 1, 29999, 100);
	}

	public void testOnRandomTask(int relNumber, int addrLower, int addrUpper, int duplicationCount) {
		Task task = createRandomTask(relNumber, addrLower, addrUpper, duplicationCount);
		int optimal = Main.optimalLocationSumOfDistancesByMedian(task);
		int bruteForthOptimal = bruteForthOptimal(task.kindredLocations);
		System.out.println(optimal + " " + bruteForthOptimal);
		assertEquals(optimal, bruteForthOptimal);
	}
	
	private static Task createRandomTask(int relNumber, int addrLower, int addrUpper, int duplicationCount) {
		int[] relatives = new int[relNumber];
		int i = 0;
		for ( ;i < relNumber - duplicationCount; i++) {
			relatives[i] = Utils.random(addrLower, addrUpper);
		}
		
		for (;i < relNumber; i++) {
			int idx = Utils.random(0, relNumber - duplicationCount - 1);
			relatives[i] = relatives[idx]; 
		}
		
		return new Task(relatives);
	}
	
	private static int bruteForthOptimal(int... streetNums) {
		int optimal = Integer.MAX_VALUE;
		for (int i = 0; i < streetNums.length; i++) {
			int addr = streetNums[i];
			int total = Main.weight(addr, streetNums);
			if (total < optimal) {
				optimal = total;
			}
		}
		
		return optimal;
	}
}
